﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
using G3.Controller;


namespace G3
{
    public partial class GraphicPanel : UserControl
    {
        public GraphicPanel()
        {            
            InitializeComponent();
        }

        #region Representation and implementation

        private Pen myPen;
        private Graphics myGraphics;

        /// <summary>
        /// az autó képe
        /// </summary>
        private Image carImage;

        /// <summary>
        /// az autó pozíciója
        /// </summary>
        private Point carPlace;

        /// <summary>
        /// az autó helyzete az x tengelyhez képest  2pi közt
        /// </summary>
        private double carAngle;

        /// <summary>
        /// az autó kirajzolása egy megadott pozícióra
        /// </summary>
        /// <param name="carPlace">képpont, ahová az autó kirajzolódik</param>
        /// <param name="carAngle">az autó helyzete (0..2pi) az x tengelyhez képest</param>
        private void DrawCar(Point carPlace, double carAngle)
        {
            this.carPlace = new Point(/*(int)Math.Round(Map.StartPos.x) */0
                + carPlace.X, /*(int)Math.Round(Map.StartPos.y)*/0 + carPlace.Y);
            this.carAngle = carAngle;
            this.GraphicPanel_Paint(this, null);

            //this.Refresh();

            //viewfield

        }

        /// <summary>
        /// Map típusú objektumból képet generál és a háttérbe rakja
        /// </summary>
        private void DrawMap()
        {
            Bitmap backgroundBmp = new Bitmap(Map.MapWidth, Map.MapHeight);            
                        
            for (int i = 0; i < Map.MapWidth; ++i)
            {
                for (int j = 0; j < Map.MapHeight; ++j)
                {                   
                    


                    backgroundBmp.SetPixel(i, j, Map.GetSurface(i, j).texture.GetPixel(i % Map.GetSurface(i, j).texture.Width, j % Map.GetSurface(i, j).texture.Height));
                }
            }

            this.BackgroundImage = backgroundBmp;
            this.BackgroundImageLayout = ImageLayout.None;                        
        }

        #endregion

        #region Interface        
         
        public void SetMap(String mapPath)
        {
            this.Cursor = Cursors.WaitCursor;

            Map.LoadMap(mapPath);
            this.DrawMap();

            this.SetCar(carImage);

            //Size newSize = new Size(Map.MapWidth, Map.MapHeight);
            this.SetBounds(this.Bounds.X, this.Bounds.Y, Map.MapWidth, Map.MapHeight);
            this.MaximumSize = this.Size;
            this.MinimumSize = this.Size;

            this.Cursor = Cursors.Cross;
        }

        /// <summary>
        /// az autó képének betöltése
        /// </summary>
        /// <param name="carImage">képfálj, az autót ábrázolja</param>
        public void SetCar(Image carImage)
        {
            this.carImage = carImage;

            carPlace = new Point((int)Math.Round(Map.StartPos.x), (int)Math.Round(Map.StartPos.y));
            carAngle = Math.PI / 2;
            this.DrawCar(new Point((int)Math.Round(Map.StartPos.x), (int)Math.Round(Map.StartPos.y)),
                carAngle);
        }

        public void ResetCar()
        {
            this.DrawCar(new Point((int)Math.Round(Map.StartPos.x),(int)Math.Round(Map.StartPos.y)),0);
        }

        /// <summary>
        /// a panel alaphelyzetbe állítása
        /// </summary>
        public void ClearPanel()
        {
            myGraphics.Clear(Color.Transparent);
            this.BackgroundImage = null;            
            this.carImage = null;
            this.carAngle = 0;
            this.carPlace = Point.Empty;
        }

        /// <summary>
        /// frissíti a térképet
        /// </summary>
        /// <param name="carPos">az autó köv pozíciója</param>
        /// <param name="carAngle">0 és 2pi közti érték, mely megadja az autó x tengelyhez valóviszonyát</param>
        public void RefreshMap(Point carPos, double carAngle)
        {
            this.DrawCar(carPos, carAngle);
        }
        
        public void Initialize(String mapPath, Image carImage)
        {
            SetMap(mapPath);
            SetCar(carImage);
            //RefreshMap(map.startPos.toPoint(), Math.PI/2); //ez majd kell, de még nem fordul le
        }


        #endregion


        private void GraphicPanel_Paint(object _sender, PaintEventArgs _e)
        {
            myGraphics = this.CreateGraphics();            
            if (this.BackgroundImage != null) myGraphics.DrawImage(this.BackgroundImage, 0, 0);              
            if (this.carImage != null)
            {                
                double alfa = Math.PI / 2 - carAngle;                
                double a = carImage.Size.Width;
                double b = carImage.Size.Height;
                Point A, B, C, D;
                Point e, f;
                e = new Point((int)Math.Round(a / 2 * (-Math.Cos(alfa))), (int)Math.Round(a / 2 * (Math.Sin(alfa))));
                f = new Point((int)Math.Round(b / 2 * Math.Sin(alfa)), (int)Math.Round(b / 2 * Math.Cos(alfa)));
                A = new Point(carPlace.X + f.X + e.X, carPlace.Y + f.Y + e.Y);
                B = new Point(carPlace.X - f.X + e.X, carPlace.Y - f.Y + e.Y);
                C = new Point(carPlace.X - f.X - e.X, carPlace.Y - f.Y - e.Y);
                D = new Point(carPlace.X + f.X - e.X, carPlace.Y + f.Y - e.Y);

                Point[] pgPoints ={ A, D, B };

                myGraphics.DrawImage(carImage, pgPoints);
                
                //látómező
                
                /*Point parhuzamos = new Point(carPlace.X - f.X, carPlace.Y - f.Y);
                Point meroleges = new Point(carPlace.X - e.X, carPlace.Y - e.Y);
                myGraphics.DrawLine(new Pen(Brushes.Red, 2), carPlace, meroleges);
                double pMul, mMul;
                pMul = double.Parse(Parameters.GetParameter("FieldOfVisionHeight")) / Length(parhuzamos);
                mMul = double.Parse(Parameters.GetParameter("FieldOfVisionWidth")) / Length(meroleges);

                parhuzamos.X = (int)Math.Round(pMul * parhuzamos.X);
                parhuzamos.Y = (int)Math.Round(pMul * parhuzamos.Y);
                meroleges.X = (int)Math.Round(mMul / 2 * meroleges.X);
                meroleges.Y = (int)Math.Round(mMul / 2 * meroleges.Y);

                Point sA, sB, sC, sD;
                sA = new Point(carPlace.X + meroleges.X, carPlace.Y + meroleges.Y);
                sB = new Point(carPlace.X - meroleges.X, carPlace.Y - meroleges.Y);
                sC = new Point(sA.X + parhuzamos.X, sA.Y + parhuzamos.Y);
                sD = new Point(sB.X + parhuzamos.X, sB.Y + parhuzamos.Y);
                
                Point[] pArray=new Point[4];
                pArray[0] = sA;
                pArray[1] = sB;
                pArray[2] = sC;
                pArray[3] = sD;

                myGraphics.DrawLine(new Pen(Color.Red, 1), sA, sB);
                //myGraphics.DrawLine(new Pen(Color.Red, 1), sC, sD);*/
            }
            myGraphics.Dispose();

        }

        private double Length(Point p)
        {
            return Math.Sqrt(p.X * p.X + p.Y * p.Y);
        }
    }
}
